package p2p

import (
	"core"
	"fmt"
	"protocol"
	"strings"
	"time"
)

type P2PServer struct {
	peerlist       *map[string]Peer
	userlist       *ConnectedPeerHead
	peerwaitlist   *map[string]Node
	service        map[string]chan protocol.Message
	sendmsgpool    chan protocol.Message
	receivemsgpool chan protocol.Message
}

//先调用此函数
func NewServer() P2PServer {
	InitPeer()
	server := P2PServer{
		peerlist:       &peerlist,
		userlist:       &userlist,
		peerwaitlist:   &peerwaitlist,
		service:        make(map[string]chan protocol.Message),
		sendmsgpool:    make(chan protocol.Message, 1024),
		receivemsgpool: make(chan protocol.Message, 1024),
	}
	return server
}

func (p *P2PServer) StartServer(service ...*protocol.Service) {

	//建立MsgPool的连接
	for _, value := range service {
		switch value.Name {
		case "Client":
			value.SendPool = p.sendmsgpool
			p.service["Client"] = value.ReceivePool

		case "AccountManager":
			value.SendPool = p.sendmsgpool
			p.service["AccountManager"] = value.ReceivePool

		case "Consensus":
			value.SendPool = p.sendmsgpool
			p.service["Consensus"] = value.ReceivePool
		}

	}

	go ListenPeer()
	go ListenUser()
	//
	time.Sleep(2 * time.Second)
	go ConnectPeer()
	//
	go p.ReceiveMsg()
	go p.SendMsg()

}
func (p *P2PServer) ReceiveMsg() {
	//死循环 对所有对等节点进行数据接收
	for {
		if len(*p.peerlist) != 0 {
			for k := range *p.peerlist {
				if (*p.peerlist)[k].rwready == false {
					v := (*p.peerlist)[k]
					v.rwready = true //判断该节点是否已经建立接收
					(*p.peerlist)[k] = v
					go func() {
						fmt.Println("开启协程")
						a := make([]byte, 4096)
						for {
							l, err := (*p.peerlist)[k].conn.Read(a[:4]) //先接收4字节数据长度
							if err != nil {
								fmt.Println("ReceiveMsg Error: ", err)
								return
							}
							fmt.Println(a[:l])
							len := core.BytesToInt(a[:4])
							fmt.Println("消息长度:", len)
							l, err = (*p.peerlist)[k].conn.Read(a[:len])
							if err != nil {
								fmt.Println("ReceiveMsg Error: ", err)
								return
							}
							fmt.Println("消息实际长度:", l)
							fmt.Println("msg: ", a[:l])
							msg := protocol.DecodeMessage(a[:l])
							if msg == nil {
								fmt.Println("DecodeMessage Error")
								fmt.Println(a[:l])
								continue
							}
							fmt.Println("接收到Msg", msg.Code)
							switch msg.Code {
							case protocol.Transaction:
								p.service["Consensus"] <- *msg
							case protocol.TransactionSuccess:
								p.service["Client"] <- *msg
							case protocol.TransactionFail:
								p.service["Client"] <- *msg

							case protocol.NewContendBlock:
								p.service["Consensus"] <- *msg
							case protocol.NewTransactionBlock:
								p.service["Consensus"] <- *msg
								p.service["AccountManager"] <- *msg

							case protocol.RegisterAccount:
								p.service["AccountManager"] <- *msg
							case protocol.RegisterAccountSuccess:
								p.service["Client"] <- *msg
							case protocol.RegisterAccountFail:
								p.service["Client"] <- *msg

							case protocol.GetContendChainNo:
								p.service["Consensus"] <- *msg
							case protocol.ContendChainNo:
								p.service["Consensus"] <- *msg
							case protocol.SyncContendChain:
								p.service["Consensus"] <- *msg
							//ContendChain由共识机制维护
							case protocol.ContendChain:
								p.service["Consensus"] <- *msg

							case protocol.GetTransactionChainNo:
								p.service["Consensus"] <- *msg
							case protocol.TransactionChainNo:
								p.service["Consensus"] <- *msg
							case protocol.SyncTransactionChain:
								p.service["Consensus"] <- *msg
							//TransactionChain由账户管理器维护
							case protocol.TransactionChain:
								p.service["AccountManager"] <- *msg

							//同步账户数据
							case protocol.GetAccountNo:
								p.service["AccountManager"] <- *msg
							case protocol.AccountNo:
								p.service["AccountManager"] <- *msg
							case protocol.SyncAccount:
								p.service["AccountManager"] <- *msg
							case protocol.Account:
								p.service["AccountManager"] <- *msg

							}
						}
					}()
				}

			}
		}
		time.Sleep(5 * time.Second)
	}
}

func (p *P2PServer) SendMsg() {

	for {
		msg := <-p.sendmsgpool
		fmt.Println("发送Msg", msg)
		fmt.Println("Msg Code = ", msg.Code)
		switch msg.Code {
		case protocol.NewContendBlock:
			p.SendAllPeer(msg)
		case protocol.NewTransactionBlock:
			p.SendAllPeer(msg)
		case protocol.RegisterAccount:
			p.SendAllPeer(msg)
		case protocol.RegisterAccountFail:
			p.SendOnePeer(msg, msg.Source)
		case protocol.RegisterAccountSuccess:
			p.SendOnePeer(msg, msg.Source)
		case protocol.Transaction:
			p.SendAllPeer(msg)
		case protocol.TransactionSuccess:
			p.SendOnePeer(msg, msg.Source)
		case protocol.TransactionFail:
			p.SendOnePeer(msg, msg.Source)

		case protocol.GetContendChainNo:
			p.SendAllPeer(msg)
		case protocol.ContendChainNo:
			p.SendOnePeer(msg, msg.Source)
		case protocol.SyncContendChain:
			p.SendOnePeer(msg, msg.Source)
		case protocol.ContendChain:
			p.SendOnePeer(msg, msg.Source)

		case protocol.GetTransactionChainNo:
			p.SendAllPeer(msg)
		case protocol.TransactionChainNo:
			p.SendOnePeer(msg, msg.Source)
		case protocol.SyncTransactionChain:
			p.SendOnePeer(msg, msg.Source)
		case protocol.TransactionChain:
			p.SendOnePeer(msg, msg.Source)

		case protocol.GetAccountNo:
			p.SendAllPeer(msg)
		case protocol.AccountNo:
			p.SendOnePeer(msg, msg.Source)
		case protocol.SyncAccount:
			p.SendOnePeer(msg, msg.Source)
		case protocol.Account:
			p.SendOnePeer(msg, msg.Source)

		}

	}
}

func (p *P2PServer) SendAllPeer(msg protocol.Message) {

	msg.Source = LocalIP //添加消息来源

	switch msg.Code {
	case protocol.Transaction:
		p.service["Consensus"] <- msg
	case protocol.TransactionSuccess:
		p.service["Client"] <- msg
	case protocol.TransactionFail:
		p.service["Client"] <- msg

	case protocol.NewContendBlock:
		p.service["Consensus"] <- msg
	case protocol.NewTransactionBlock:
		p.service["Consensus"] <- msg
		p.service["AccountManager"] <- msg

	case protocol.RegisterAccount:
		p.service["AccountManager"] <- msg
	case protocol.RegisterAccountSuccess:
		p.service["Client"] <- msg
	case protocol.RegisterAccountFail:
		p.service["Client"] <- msg

	case protocol.GetContendChainNo:
		p.service["Consensus"] <- msg
	case protocol.ContendChainNo:
		p.service["Consensus"] <- msg
	case protocol.SyncContendChain:
		p.service["Consensus"] <- msg
	//ContendChain由共识机制维护
	case protocol.ContendChain:
		p.service["Consensus"] <- msg

	case protocol.GetTransactionChainNo:
		p.service["Consensus"] <- msg
	case protocol.TransactionChainNo:
		p.service["Consensus"] <- msg
	case protocol.SyncTransactionChain:
		p.service["Consensus"] <- msg
	//TransactionChain由账户管理器维护
	case protocol.TransactionChain:
		p.service["AccountManager"] <- msg

	//同步账户数据
	case protocol.GetAccountNo:
		p.service["AccountManager"] <- msg
	case protocol.AccountNo:
		p.service["AccountManager"] <- msg
	case protocol.SyncAccount:
		p.service["AccountManager"] <- msg
	case protocol.Account:
		p.service["AccountManager"] <- msg
	}
	if len(*p.peerlist) != 0 {
		for _, v := range *p.peerlist {
			a := msg.EncodeMessage()
			if a == nil {
				fmt.Println("Encode Message Error")
			} else {
				a = append(core.IntToBytes(len(a)), a...) //添加消息长度 防止TCP粘包问题
				fmt.Println("Send Meg:", a)
				_, err := v.conn.Write(a)
				if err != nil {
					fmt.Println("conn.Write Error")
				}
			}
		}

	}

}

func (p *P2PServer) SendOnePeer(msg protocol.Message, addr string) {

	if msg.Source == LocalIP {
		switch msg.Code {
		case protocol.Transaction:
			p.service["Consensus"] <- msg
		case protocol.TransactionSuccess:
			p.service["Client"] <- msg
		case protocol.TransactionFail:
			p.service["Client"] <- msg

		case protocol.NewContendBlock:
			p.service["Consensus"] <- msg
		case protocol.NewTransactionBlock:
			p.service["Consensus"] <- msg
			p.service["AccountManager"] <- msg

		case protocol.RegisterAccount:
			p.service["AccountManager"] <- msg
		case protocol.RegisterAccountSuccess:
			p.service["Client"] <- msg
		case protocol.RegisterAccountFail:
			p.service["Client"] <- msg

		case protocol.GetContendChainNo:
			p.service["Consensus"] <- msg
		case protocol.ContendChainNo:
			p.service["Consensus"] <- msg
		case protocol.SyncContendChain:
			p.service["Consensus"] <- msg
		//ContendChain由共识机制维护
		case protocol.ContendChain:
			p.service["Consensus"] <- msg

		case protocol.GetTransactionChainNo:
			p.service["Consensus"] <- msg
		case protocol.TransactionChainNo:
			p.service["Consensus"] <- msg
		case protocol.SyncTransactionChain:
			p.service["Consensus"] <- msg
		//TransactionChain由账户管理器维护
		case protocol.TransactionChain:
			p.service["AccountManager"] <- msg

		//同步账户数据
		case protocol.GetAccountNo:
			p.service["AccountManager"] <- msg
		case protocol.AccountNo:
			p.service["AccountManager"] <- msg
		case protocol.SyncAccount:
			p.service["AccountManager"] <- msg
		case protocol.Account:
			p.service["AccountManager"] <- msg
			return
		}
	}

	if len(*p.peerlist) != 0 {
		for _, v := range *p.peerlist {
			//先找到对应的conn
			temp := v.conn.RemoteAddr().String()
			temp = temp[:strings.IndexByte(temp, ':')] //截取IP值
			if msg.Source == temp {
				msg.Source = LocalIP
				a := msg.EncodeMessage()
				if a == nil {
					fmt.Println("Encode Message Error")
				} else {
					a = append(core.IntToBytes(len(a)), a...) //添加消息长度 防止TCP粘包问题
					fmt.Println("Send Meg:", a)
					_, err := v.conn.Write(a)
					if err != nil {
						fmt.Println("conn.Write Error")
					}
				}
				break
			}
		}
	}
}
